//
//  CHJVideoEditManger.m
//  CHJVideoKit_Example
//
//  Created by jiaxuzhou on 2017/12/2.
//  Copyright © 2017年 jxzjxz. All rights reserved.
//

#import "CHJVideoEditManger.h"
#import "YXVideoSDKDriver.h"
#import "CHJCaptureDataSource.h"
#import "MPTSpeedUploadVideoEditor.h"
#import "YXVideoUtil.h"

YXVideoSDKDriver *sdkDriver__ = nil;
@interface CHJVideoEditManger ()
<
YXVideoSDKDriverDelegate
>

///照片管理器
@property (nonatomic, strong) PHCachingImageManager *imageManager;

@end

@implementation CHJVideoEditManger

- (void)dealloc
{
    NSLog(@"%s",__func__);
}
/**
 从拍摄的视频片段进入
 
 @return CHJVideoEditManger
 */
- (id)initWithCapture
{
    if (self = [super init])
    {
       _videoEngine = [[YXVideoSDKDriver alloc] initWithVideoClips:[[CHJCaptureDataSource shareDataSource] getVideoClips]];
        _videoEngine.delegate = self;
    }

    return self;
}

+ (void)getVideoParamByRect:(CGRect)rect asset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange composition:(AVMutableComposition **)composition videoComposition:(AVMutableVideoComposition **)videoComposition outAudioMix:(AVAudioMix **)outAudioMix
{
    YXVideoCropFromAsset(asset, timeRange, rect, rect.size, composition, videoComposition, outAudioMix);

}

+ (void)exportVideoParamByRect:(CGRect)rect asset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange outputPath:(NSString *)outputPath transcoding:(NSString *)transcoding success:(void (^)(void))success fail:(void (^)(void))fail blockSDK:(void (^)(YXVideoSDKDriver *))blockSDK
{
    if ([transcoding isEqualToString:@"1"])
    {
        success();
        return;
    }
    AVMutableComposition *composition;
    AVMutableVideoComposition *videoComposition;
    AVAudioMix *outAudioMix;
    [self getVideoParamByRect:rect asset:asset timeRange:timeRange composition:&composition videoComposition:&videoComposition outAudioMix:&outAudioMix];    
    [self exportVideoParamByRect:rect asset:asset timeRange:timeRange composition:composition videoComposition:videoComposition outAudioMix:outAudioMix outputPath:outputPath success:success fail:fail blockSDK:blockSDK];
}


+ (void)exportVideoParamByRect:(CGRect)rect asset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange composition:(AVMutableComposition *)composition videoComposition:(AVMutableVideoComposition *)videoComposition outAudioMix:(AVAudioMix *)outAudioMix outputPath:(NSString *)outputPath success:(void (^)(void))success fail:(void (^)(void))fail  blockSDK:(void (^)(YXVideoSDKDriver *))blockSDK;
{
    dispatch_async(dispatch_get_main_queue(), ^{
       YXVideoSDKDriver *sdkDriver = [[YXVideoSDKDriver alloc] initWithComposition:composition videoComposition:videoComposition audioMix:outAudioMix];
        
        [sdkDriver exportVideoToPath:outputPath fileType:AVFileTypeMPEG4 bitRate:YXVideoBitrateAutoConfig(rect.size) exporting:^(CGFloat progress)
         {
             NSLog(@"*********倒出视频:%@",@(progress));
         } exported:^
         {
//             dispatch_sync(dispatch_get_main_queue(), ^{
             
                 NSLog(@"导出视频成功");
                 
                 if (success)
                 {
                     success();
                 }
                 
//             });
             
         } exportCanceled:^
         {
//             dispatch_sync(dispatch_get_main_queue(), ^{
             
                 NSLog(@"导出视频失败");
                 
                 if (fail)
                 {
                     fail();
                 }
                 
//             });
             
         } exportFailed:^(NSError *error)
         {
//             dispatch_sync(dispatch_get_main_queue(), ^{
             
                 NSLog(@"导出视频失败");
                 
                 if (fail)
                 {
                     fail();
                 }
                 
//             });
         }];
        
        blockSDK(sdkDriver);
    });
    
    

  
    
//    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
//    exportSession.videoComposition = videoComposition;
//    exportSession.shouldOptimizeForNetworkUse = YES;
//    exportSession.audioMix = outAudioMix;
//    exportSession.outputURL = [NSURL fileURLWithPath:outputPath];
//    exportSession.outputFileType = AVFileTypeMPEG4;
//
//    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
//
//    [exportSession exportAsynchronouslyWithCompletionHandler:^{
//        dispatch_semaphore_signal(semaphore);
//        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
//            dispatch_sync(dispatch_get_main_queue(), ^{
//
//                NSLog(@"导出视频成功");
//
//                if (success)
//                {
//                    success();
//                }
//
//            });
//        } else {
//            dispatch_sync(dispatch_get_main_queue(), ^{
//
//                NSLog(@"导出视频成功");
//
//                if (fail)
//                {
//                    fail();
//                }
//
//            });
//        }
//    }];
}

/**
 从手机相册里选择的视频
 @param assetP 手机相册元素对象
 @return CHJVideoEditManger
 */

- (void)initWithAsset:(AVAsset *)asset frame:(CGRect)rect
{
    AVMutableComposition *composition;
    AVMutableVideoComposition *videoComposition;
    AVAudioMix *outAudioMix;
    
    [[self class] getVideoParamByRect:rect asset:asset timeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) composition:&composition videoComposition:&videoComposition outAudioMix:&outAudioMix];
    
    _videoEngine = [[YXVideoSDKDriver alloc] initWithComposition:composition videoComposition:videoComposition audioMix:nil];
    _videoEngine.delegate = self;
    
}

- (void)initWithPHAsset:(PHAsset *)assetP progress:(void (^)(CGFloat flt))progressblock finish:(void (^)(BOOL isSuccess))finish
{
    _imageManager = [[PHCachingImageManager alloc]init];
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    options.networkAccessAllowed = YES;
    
    
    [self.imageManager requestAVAssetForVideo:assetP options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        
        if (asset)
        {
            AVAsset *ass = asset;
            if (ass != nil)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    MPTSpeedUploadVideoEditor *editor = [[MPTSpeedUploadVideoEditor alloc] initWithAsset:ass withRange:kCMTimeRangeZero];
                    _videoEngine = [[YXVideoSDKDriver alloc] initWithComposition:editor.composition videoComposition:editor.videoComposition audioMix:editor.audioMix];
                    _videoEngine.delegate = self;
                    
                    if (finish)
                    {
                        finish(YES);
                    }
                });
            }
        }
    }];
}

- (void)initWithPHAsset:(PHAsset *)assetP composition:(AVComposition *)composition videoComposition:(AVVideoComposition *)videoComposition audioMix:(AVAudioMix *)audioMix progress:(void (^)(CGFloat flt))progressblock finish:(void (^)(BOOL isSuccess))finish
{
    _imageManager = [[PHCachingImageManager alloc]init];
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    options.networkAccessAllowed = YES;
    
    
    [self.imageManager requestAVAssetForVideo:assetP options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        
        if (asset)
        {
            AVAsset *ass = asset;
            if (ass != nil)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    MPTSpeedUploadVideoEditor *editor = [[MPTSpeedUploadVideoEditor alloc] initWithAsset:ass withRange:kCMTimeRangeZero];
                    _videoEngine = [[YXVideoSDKDriver alloc] initWithComposition:composition?composition:(AVComposition *)editor.composition videoComposition:videoComposition?videoComposition:editor.videoComposition audioMix:audioMix?audioMix:editor.audioMix];
                    _videoEngine.delegate = self;
                    
                    if (finish)
                    {
                        finish(YES);
                    }
                });
            }
        }
    }];
}

- (void)initWithAVAsset:(AVAsset *)asset
{

    MPTSpeedUploadVideoEditor *editor = [[MPTSpeedUploadVideoEditor alloc] initWithAsset:asset withRange:kCMTimeRangeZero];
    _videoEngine = [[YXVideoSDKDriver alloc] initWithComposition:editor.composition videoComposition:editor.videoComposition audioMix:editor.audioMix];
    _videoEngine.delegate = self;
}

- (void)changeRenderViewClearColor:(UIColor *)color
{
    self.videoEngine.renderViewClearColor = color;
}

- (void)seekWithTextureCallback:(void (^)(void))success
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        if (success)
        {
            success();
        }
    });
}

#pragma mark -- *****************************************  字幕相关  *****************************************

// 字幕
- (void)updateSubtitles:(NSArray <NSDictionary <NSString *, NSString *> *> *)subtitles
{
    [self.videoEngine updateSubtitles:subtitles];
}

/**
 添加一个字幕 Model
 
 @param textModel model
 */
- (void)arrangeTextModel:(YXVideoTextModel *)textModel
{
    [self.videoEngine arrangeTextModel:textModel];
}


/**
 移除一个字幕 Model
 
 @param textModel model
 */
- (void)removeTextModel:(YXVideoTextModel *)textModel
{
    [self.videoEngine removeTextModel:textModel];
}


/**
 移除 index位置上的 model
 
 @param index index
 */
- (void)removeTextModelAtIndex:(NSUInteger)index
{
    [self.videoEngine removeTextModelAtIndex:index];
}


/**
 移除所有 model
 */
- (void)removeAllTextModel
{
    [self.videoEngine removeAllTextModel];
}


/**
 显示已经加载的 model
 */
- (void)showArrangedTextModel
{
    [self.videoEngine showArrangedTextModel];
}


/**
 隐藏所有 model
 */
- (void)hideArrangedTextModel
{
    [self.videoEngine hideArrangedTextModel];
}


#pragma mark -- *****************************************  贴纸相关  *****************************************

// 贴纸

/**
 添加一个贴纸
 
 @param paster 贴纸实例
 */
- (void)addPaster:(YXVideoPasterObject *)paster
{
    [self.videoEngine addPaster:paster];
}


/**
 移除一个贴纸
 
 @param paster 贴纸实例
 */
- (void)removePaster:(YXVideoPasterObject *)paster
{
    [self.videoEngine removePaster:paster];
}


/**
 获取全部已经添加的贴纸
 
 @return 贴纸数组
 */
- (NSArray <YXVideoPasterObject *> *)getAddedPasters
{
    return [self.videoEngine getAddedPasters];
}


/**
 更新贴纸层
 */
- (void)updatePasterLayer
{
    [self.videoEngine updatePasterLayer];
}


/**
 隐藏贴纸层
 */
- (void)hidePasterLayer
{
    [self.videoEngine hidePasterLayer];
}


/**
 显示贴纸层
 */
- (void)showPasterLayer
{
    [self.videoEngine showPasterLayer];
}

// layer
- (void)arrangeTextLayerWithText:(NSString *)text
                       textColor:(UIColor *)textColor
                 backgroundColor:(UIColor *)backgroundColor
                            font:(UIFont *)font
                        position:(CGPoint)position
                       transform:(CGAffineTransform)transform
                          forKey:(NSString *)key
{
    [self.videoEngine arrangeTextLayerWithText:text
                                     textColor:textColor
                               backgroundColor:backgroundColor
                                          font:font
                                      position:position
                                     transform:transform
                                        forKey:key];
}

- (void)arrangeLayer:(CALayer *)layer forKey:(NSString *)key
{
    [self.videoEngine arrangeLayer:layer forKey:key];
}

- (void)removeLayerWithKey:(NSString *)key
{
    [self.videoEngine removeLayerWithKey:key];
}

#pragma mark -- *****************************************  UI播放相关  *****************************************

/**
 播放
 */
- (void)play
{
    [self.videoEngine play];
}

/**
 暂停
 */
- (void)pause
{
    [self.videoEngine pause];
}

#pragma mark -- *****************************************  声音相关  *****************************************

/**
 变声控制
 
 @param pitch 音调
 @param speed 语速
 */
- (void)suitVideoWithPitch:(NSInteger)pitch speed:(CGFloat)speed
{
    [self.videoEngine suitVideoWithPitch:pitch speed:speed];
}

/**
 视频原声开关
 
 @param enable 是否开启
 */
- (void)enableOriginalSound:(BOOL)enable
{
    [self.videoEngine enableOriginalSound:enable];
}

// 音乐
- (void)setMusicVolume:(CGFloat)volume //背景
{
    [self.videoEngine setMusicVolume:volume];
}

- (void)setOriginVolume:(CGFloat)volume //原音
{
    [self.videoEngine setOriginVolume:volume];
}


#pragma mark -- *************************************  切换滤镜和音乐相关  *****************************************

/**
 加载效果 model。在切换滤镜的时候调用
 
 @param videoEffectModel 效果 model
 @param musicPath 如果给视频陪背景音乐 音乐的路径
 @param timeRange 音乐循环区间
 @param doneHandler 完成加载 model回调
 */
- (void)loadVideoEffectModel:(YXVideoEffectModel *)videoEffectModel musicPath:(NSString *)musicPath trackRange:(CMTimeRange)timeRange whenDone:(void (^)())doneHandler
{
    [self.videoEngine loadVideoEffectModel:videoEffectModel
                                 musicPath:musicPath
                                trackRange:timeRange
                                  whenDone:doneHandler];
}

/**
 加载效果 model 切换滤镜没有音乐选择时调用
 @param videoEffectModel 效果 model
 @param doneHandler 完成加载 model回调
 */
- (void)loadVideoEffectModel:(YXVideoEffectModel *)videoEffectModel whenDone:(void (^)())doneHandler
{
    [self.videoEngine loadVideoEffectModel:videoEffectModel whenDone:doneHandler];
}

#pragma mark -- *****************************************  剪辑相关  *****************************************

/**
 seek 使用场景：改变了滑块范围 即：快进 快退
 
 @param second 时间
 */
- (void)seekToSecondWithHandleDecode:(CGFloat)second
{
    [self.videoEngine seekToSecondWithHandleDecode:second];
}

/**
 seek 使用场景：改变了滑块范围 即：快进 快退
 
 @param progress 进度百分比
 */
- (void)seekToProgressWithHandleDecode:(CGFloat)progress
{
    [self.videoEngine seekToProgressWithHandleDecode:progress];
}

/**
 结束滑动时调用 用于记录停止位置
 */
- (void)seekServiceDone
{
    [self.videoEngine seekServiceDone];
}


#pragma mark -- *****************************************  导出相关  *****************************************

/**
 导出方法
 
 @param path 导出路径
 @param fileType 文件 type 一般 mp4使用 AVFileTypeMPEG4
 @param bitRate 导出文件的比特率
 @param exportingBlock 正在导出的回调
 @param exportedBlock 导出完成的回调
 @param exportCanceledBlock 导出取消的回调
 @param exportFailed 导出失败的回调
 */
- (void)exportVideoToPath:(NSString *)path fileType:(NSString *)fileType bitRate:(NSInteger)bitRate exporting:(void (^)(CGFloat progress))exportingBlock exported:(void (^)())exportedBlock exportCanceled:(void (^)())exportCanceledBlock exportFailed:(void (^)(NSError *error))exportFailed
{
    [self.videoEngine exportVideoToPath:path
                               fileType:fileType
                                bitRate:bitRate
                              exporting:exportingBlock
                               exported:exportedBlock
                         exportCanceled:exportCanceledBlock
                           exportFailed:exportFailed];
}

/**
 取消导出
 */
- (void)cancelExport
{
    [self.videoEngine cancelExport];
}

#pragma mark -- *****************************************  获取资源相关  *****************************************

/// 获取截图
- (void)getThumbnailsWithCount:(NSInteger)count scaled:(CGFloat)scale compeletionC:(void (^)(UIImage *image, NSUInteger index))callback
{
    [self.videoEngine GetThumbnailsWithCount:count scaled:scale compeletionC:callback];
}
/**
 绘制视频的UIView
 
 @return UIView
 */
- (UIView *)getRenderView
{
    return self.videoEngine.renderView;
}

/**
 视频剪切后的范围
 
 @return 范围
 */
- (CMTimeRange)getVideoRange
{
    return self.videoEngine.videoRange;
}

/**
 获取视频尺寸
 
 @return 尺寸
 */
- (CGSize)getVideoSize
{
    return self.videoEngine.videoSize;
}

/**
 获取视频时长
 
 @return 时长
 */
- (CGFloat)getVideoDuration
{
    return self.videoEngine.videoDuration;
}


/**
 是否正在播放视频
 
 @return YES  NO
 */
- (BOOL)getIsPlaying
{
    return self.videoEngine.isPlaying;
}

#pragma mark -- *****************************************  delegate相关  *****************************************


/**
 播放回调
 
 @param driver driver实例
 @param time 播放当前时间
 @param duration 总时间
 */
- (void)driver:(YXVideoSDKDriver *)driver played:(CGFloat)time total:(CGFloat)duration
{
    if ([self.delegate respondsToSelector:@selector(chj_driver:played:total:)]) {
        [self.delegate chj_driver:self played:time total:duration];
    }
}



/**
 开始播放回调
 
 @param driver driver实例
 */
- (void)driverDoPlay:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverDoPlay:)]) {
        [self.delegate chj_driverDoPlay:self];
    }
}


/**
 暂停播放回调
 
 @param driver driver实例
 */
- (void)driverDoPause:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverDoPause:)]) {
        [self.delegate chj_driverDoPause:self];
    }
}


/**
 完成整个视频播放回调
 
 @param driver driver实例
 */
- (void)driverPlayback:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverPlayback:)]) {
        [self.delegate chj_driverPlayback:self];
    }
}


/**
 加载视频播放失败回调, 需要重新加载
 
 @param driver driver实例
 */
- (void)driverLoadVideoFailed:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverLoadVideoFailed:)]) {
        [self.delegate chj_driverLoadVideoFailed:self];
    }
}


/**
 变声服务开始
 
 @param driver driver
 */
- (void)driverVoiceChangeServiceStarted:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverVoiceChangeServiceStarted:)]) {
        [self.delegate chj_driverVoiceChangeServiceStarted:self];
    }
}

/**
 变声服务完成
 
 @param driver driver
 */
- (void)driverVoiceChangeServiceDone:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverVoiceChangeServiceDone:)]) {
        [self.delegate chj_driverVoiceChangeServiceDone:self];
    }
}

/**
 变声服务取消
 
 @param driver driver
 */
- (void)driverVoiceChangeServiceCancelled:(YXVideoSDKDriver *)driver
{
    if ([self.delegate respondsToSelector:@selector(chj_driverVoiceChangeServiceCancelled:)]) {
        [self.delegate chj_driverVoiceChangeServiceCancelled:self];
    }
}
         
@end
